﻿using System;
using BHS.TFSChangsetAnalyser.Model;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace BHS.TFSChangsetAnalyser.UnitTests
{
    [TestClass]
    public class ChangesetAnalysisResultsTests
    {
        [TestMethod]
        public void AnalysisResultsAreValidEvenIfNoChangesetsArePresent()
        {
            // Arrange
            // Nothing to do

            // Act
            ChangesetAnalysisResults results = new ChangesetAnalysisResults();

            // Assert
            Assert.AreEqual(0, results.NumberOfChangesets, "NumberOfChangesets should be zero. The collection should be empty");
            Assert.AreEqual(0, results.NumberOfChanges, "NumberOfChanges should be zero. The collection should be empty");
            Assert.AreEqual(0, results.NumberOfReviewedChanges, "NumberOfReviewedChanges should be zero. The collection should be empty");
            Assert.AreEqual(0, results.PercentageChangesReviewed, "PercentageChangesReviewed should be zero. The collection should be empty");
            Assert.IsNotNull(results.ChangesetInfos, "Changeset collection should never be null");
            Assert.AreEqual(0, results.ChangesetInfos.Count, "Changeset collection should be empty");
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void CannotAddNullChangesetInfoToCollection()
        {
            // Arrange 
            ChangesetInfo newChangeset = null;
            ChangesetAnalysisResults results = new ChangesetAnalysisResults();

            // Act
            results.AddChangesetForAnalysis(newChangeset);

            // Assert
            // Nothing to do - will throw an exception
        }

        [TestMethod]
        public void AddUnReviewedChangesetsToCollection()
        {
            // Arrange
            ChangesetAnalysisResults results = new ChangesetAnalysisResults(); 
            ChangesetInfo changeset1 = new ChangesetInfo
                                           {
                                                SubmittedDate  = DateTime.Now,
                                                Submitter = "Bryan",
                                                NumberOfChanges = 10,
                                                NumberOfReviewableChanges = 10
                                           };
            ChangesetInfo changeset2 = new ChangesetInfo
                                           {
                                               SubmittedDate = DateTime.Now,
                                               Submitter = "Bryan",
                                               NumberOfChanges = 5,
                                               NumberOfReviewableChanges = 5
                                           };

            // Act
            results.AddChangesetForAnalysis(changeset1);            
            results.AddChangesetForAnalysis(changeset2);

            // Assert
            Assert.AreEqual(2, results.NumberOfChangesets, "Number of Changesets is incorrect");
            Assert.AreEqual(15, results.NumberOfChanges, "Number of Changes is incorrect");
            Assert.AreEqual(0, results.NumberOfReviewedChanges, "Number of Reviewed Changes is incorrect");
            Assert.AreEqual(0, results.PercentageChangesReviewed, "Percentage Reviewed is incorrect");
        }

        [TestMethod]
        public void NumberOfChangesCaluclationShouldBeUsingReviewableChangesSourceProperty()
        {
            // Arrange
            ChangesetAnalysisResults results = new ChangesetAnalysisResults(); 
            ChangesetInfo changeset1 = new ChangesetInfo
                                           {
                                                SubmittedDate  = DateTime.Now,
                                                Submitter = "Bryan",
                                                NumberOfChanges = 10,
                                                NumberOfReviewableChanges = 10
                                           };
            ChangesetInfo changeset2 = new ChangesetInfo
                                           {
                                               SubmittedDate = DateTime.Now,
                                               Submitter = "Bryan",
                                               NumberOfChanges = 20,
                                               NumberOfReviewableChanges = 5
                                           };

            // Act
            results.AddChangesetForAnalysis(changeset1);            
            results.AddChangesetForAnalysis(changeset2);

            Assert.AreEqual(2, results.NumberOfChangesets, "Number of Changesets is incorrect");
            Assert.AreEqual(15, results.NumberOfChanges, "Number of Changes is incorrect");
        }

        [TestMethod]
        public void NumberOfReviewedChangesCalculationIsCorrect()
        {
            // Arrange
            ChangesetAnalysisResults results = new ChangesetAnalysisResults();
            ChangesetInfo changeset1 = new ChangesetInfo
            {
                SubmittedDate = DateTime.Now,
                Submitter = "Bryan",
                NumberOfChanges = 10,
                NumberOfReviewableChanges = 10,
                CodeReviewer = "Jack"
            };
            ChangesetInfo changeset2 = new ChangesetInfo
                                           {
                                               SubmittedDate = DateTime.Now,
                                               Submitter = "Bryan",
                                               NumberOfChanges = 20,
                                               NumberOfReviewableChanges = 5
                                           };

            // Act
            results.AddChangesetForAnalysis(changeset1);
            results.AddChangesetForAnalysis(changeset2);

            // Assert
            Assert.AreEqual(10, results.NumberOfReviewedChanges, "Number of Reviewed Changes is incorrect");
            Assert.AreEqual(67, results.PercentageChangesReviewed, "Percentage Reviewed is incorrect.");
        }

        [TestMethod]
        public void PercentageRevieweddCalculationAvoidsDivideByZeroError()
        {
            // Arrange 
            ChangesetInfo newChangeset = new ChangesetInfo
                                             {
                                                 NumberOfChanges = 0,
                                                 NumberOfReviewableChanges = 0,
                                                 CodeReviewer = string.Empty
                                             };
            ChangesetAnalysisResults results = new ChangesetAnalysisResults();

            results.AddChangesetForAnalysis(newChangeset);
            
            // Act
            int percentageReviewed = results.PercentageChangesReviewed;

            // Assert
            Assert.AreEqual(0, percentageReviewed, "Percentage Reviewed is incorrect.");
        }

        [TestMethod]
        public void ResultsCanBeCleared()
        {
            // Arrange
            ChangesetAnalysisResults results = new ChangesetAnalysisResults();
            ChangesetInfo changeset1 = new ChangesetInfo
                                           {
                                               SubmittedDate = DateTime.Now,
                                               Submitter = "Bryan",
                                               NumberOfChanges = 10,
                                               NumberOfReviewableChanges = 10,
                                               CodeReviewer = "Jack"
                                           };
            ChangesetInfo changeset2 = new ChangesetInfo
                                           {
                                               SubmittedDate = DateTime.Now,
                                               Submitter = "Bryan",
                                               NumberOfChanges = 20,
                                               NumberOfReviewableChanges = 5
                                           };

            results.AddChangesetForAnalysis(changeset1);
            results.AddChangesetForAnalysis(changeset2);

            // Act
            results.ClearAnalysisResults();
   
            // Assert
            Assert.AreEqual(0, results.NumberOfChangesets, "NumberOfChangesets should be zero. The collection should be empty");
            Assert.AreEqual(0, results.NumberOfChanges, "NumberOfChanges should be zero. The collection should be empty");
            Assert.AreEqual(0, results.NumberOfReviewedChanges, "NumberOfReviewedChanges should be zero. The collection should be empty");
            Assert.AreEqual(0, results.PercentageChangesReviewed, "PercentageChangesReviewed should be zero. The collection should be empty");
            Assert.IsNotNull(results.ChangesetInfos, "Changeset collection should never be null");
            Assert.AreEqual(0, results.ChangesetInfos.Count, "Changeset collection should be empty");
        }

        [TestMethod]
        public void HasResultsIsFalseIfNoResultsAdded()
        {
            // Arrange
            ChangesetAnalysisResults results = new ChangesetAnalysisResults();

            // Act
            bool hasResults = results.HasResults;

            // Assert
            Assert.IsFalse(hasResults, "HasResults should be false because none were addded");
        }

        [TestMethod] 
        public void HasResultsReturnsFalseIfResultsAreCleared()
        {
            // Arrange
            ChangesetAnalysisResults results = new ChangesetAnalysisResults();
            ChangesetInfo changeset1 = new ChangesetInfo
                                           {
                                               SubmittedDate = DateTime.Now,
                                               Submitter = "Bryan",
                                               NumberOfChanges = 10,
                                               NumberOfReviewableChanges = 10,
                                               CodeReviewer = "Jack"
                                           };
            ChangesetInfo changeset2 = new ChangesetInfo
                                           {
                                               SubmittedDate = DateTime.Now,
                                               Submitter = "Bryan",
                                               NumberOfChanges = 20,
                                               NumberOfReviewableChanges = 5
                                           };

            results.AddChangesetForAnalysis(changeset1);
            results.AddChangesetForAnalysis(changeset2);
            results.ClearAnalysisResults();
   
            // Act
            bool hasResults = results.HasResults;
            
            // Assert
            Assert.IsFalse(hasResults, "HasResults should be false because we've cleared the results");
        }

        [TestMethod]
        public void HasResultsReturnsTrueIfResultsArePresent()
        {
            // Arrange
            ChangesetAnalysisResults results = new ChangesetAnalysisResults();
            ChangesetInfo changeset1 = new ChangesetInfo
                                           {
                                               SubmittedDate = DateTime.Now,
                                               Submitter = "Bryan",
                                               NumberOfChanges = 10,
                                               NumberOfReviewableChanges = 10,
                                               CodeReviewer = "Jack"
                                           };
            ChangesetInfo changeset2 = new ChangesetInfo
                                           {
                                               SubmittedDate = DateTime.Now,
                                               Submitter = "Bryan",
                                               NumberOfChanges = 20,
                                               NumberOfReviewableChanges = 5
                                           };

            results.AddChangesetForAnalysis(changeset1);
            results.AddChangesetForAnalysis(changeset2);

            // Act
            bool hasResults = results.HasResults;

            // Assert
            Assert.IsTrue(hasResults, "HasResults should be true because we have added changesets");
        }
    }
}
